package com.harveyspace.aes.social.sina;

import com.harveyspace.aes.core.utils.HttpUtil;
import com.harveyspace.aes.core.utils.JsonUtil;
import com.harveyspace.aes.social.Oauth;
import com.harveyspace.aes.social.SocialConfig;
import com.harveyspace.aes.social.exception.SocialException;
import com.harveyspace.aes.social.pojo.AccessTokenInfo;
import com.harveyspace.aes.social.pojo.SocialiteUserInfo;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 新浪第三方登录
 *
 * @Author <a href="harveyer@163.com">harvey</a>
 * @date 2018/2/9
 */
public class OauthSina extends Oauth {
    
	private final String TOKEN_URL = "https://api.weibo.com/oauth2/access_token";
	private final String USER_INFO_URL = "https://api.weibo.com/2/users/show.json";

	/**
     * @param socialConfig 配置信息
     */
    public OauthSina(SocialConfig socialConfig) {
        super(socialConfig);
        AUTH_URL = "https://api.weibo.com/oauth2/authorize";
    }
    
	/**
	 * 获取授权url
	 *
	 * @param state OAuth2.0标准协议建议，利用state参数来防止CSRF攻击
	 * @return String
	 */
	@Override
    public String getAuthorizeUrl(String state) {
		return super.getAuthorizeUrl(state);
	}
	
	/**
	 * 获取用户信息
	 *
	 * @param accessToken AccessToken
	 * @param uid 用户id
	 * @return SinaUserInfo
	 * @throws SocialException 登录异常
	 */
	private SinaUserInfo getUserInfo(String accessToken, String uid) throws SocialException {
		Map<String, String> params = new HashMap<>();
		params.put("uid", uid);
		params.put("access_token", accessToken);

        String result;
        try {
            result = HttpUtil.getString(initParams(USER_INFO_URL, params), 1);
        } catch (IOException e) {
            String errorMessage = String.format("通过 accessToken[%s]，uid[%s] 获取用户信息异常", accessToken, uid);
            logger.error(errorMessage, e);
            throw new SocialException(errorMessage);
        }

        return JsonUtil.toObject(result, SinaUserInfo.class);
	}

    /**
     * 获取token 返回的是JSON 解析获取到Token以及OpenId
     * 
     * @param code 使用code换取token
     * @return String 返回类型
     * @throws SocialException 登录异常
     */
    @Override
    public AccessTokenInfo getAccessToken(String code) throws SocialException {
        
        Map<String, Object> params = new HashMap<>();
        params.put("code", code);
        params.put("client_id", socialConfig.getClientId());
        params.put("client_secret", socialConfig.getClientSecret());
        params.put("grant_type", "authorization_code");
        params.put("redirect_uri", socialConfig.getRedirectUri());

		String result;

		try {
			result = HttpUtil.postString(TOKEN_URL, 1, params);
		} catch (IOException e) {

			String errorMessage = String.format("通过 code[%s] 获取 access token异常", code);
			logger.error(errorMessage, e);
			throw new SocialException(errorMessage);
		}

        Map<String, Object> responseMap = JsonUtil.toMap(result);

        //返回错误码时直接返回空
        if(StringUtils.isNotBlank(MapUtils.getString(responseMap, "error_code"))){

            String errorCode = MapUtils.getString(responseMap, "error_code");
            String errorMessage = MapUtils.getString(responseMap, "error");

            throw new SocialException(String.format("通过 code[%s] 获取 access token异常:%s[%s]", code, errorMessage, errorCode));
        }

        String accessToken = MapUtils.getString(responseMap, "access_token");
        String uid = MapUtils.getString(responseMap, "uid");
        long expiresIn = MapUtils.getLongValue(responseMap, "expires_in");

        AccessTokenInfo accessTokenInfo = new AccessTokenInfo();
        accessTokenInfo.setUnionId(uid);
        accessTokenInfo.setOpenId(uid);
        accessTokenInfo.setAccessToken(accessToken);
        accessTokenInfo.setExpiresIn(expiresIn);

        return accessTokenInfo;
    }

    @Override
    public SocialiteUserInfo getSocialUserInfo(AccessTokenInfo accessTokenInfo) throws SocialException {

        String accessToken = accessTokenInfo.getAccessToken();
        String uid = accessTokenInfo.getUnionId();

        if (StringUtils.isBlank(accessToken)) {
            throw new SocialException("accessToken is Blank!");
        }

        if (StringUtils.isBlank(uid)) {
            throw new SocialException("openId is Blank!");
        }

        SocialiteUserInfo socialiteUserInfo = new SocialiteUserInfo();
        socialiteUserInfo.setUnionId(accessTokenInfo.getUnionId());
        socialiteUserInfo.setOpenId(accessTokenInfo.getOpenId());

        SinaUserInfo info = getUserInfo(accessToken, uid);

        if(null != info) {
            socialiteUserInfo.setAvatar(info.getProfileImageUrl());
            socialiteUserInfo.setNickName(info.getScreenName());
            socialiteUserInfo.setName(info.getName());
        }

        return socialiteUserInfo;
    }
}
